package Nionetwork;
//NIO Channel客户端


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;

public class NioClient {
    public static void main(String [] args)
    {
        String host="127.0.0.1";
        int port =8001;//端口对应服务器端口
        Selector selector=null;//定义端口选择器
        /**Selector端口选择器可以在服务端用，也可以在客户端用
         * */
        SocketChannel sc=null;//定义nio的客户端通道
        try{
            selector=Selector.open();//端口选择器打开
            sc=SocketChannel.open();//通道打开
            sc.configureBlocking(false);//把通道配置成非阻塞模式
            if (sc.connect(new InetSocketAddress(host,port)))//连接远端的服务器
            {
                /**连接服务器时要IP地址和端口号都要*/
                System.out.println("测试");
                sc.register(selector,SelectionKey.OP_READ);//绑定客户端的选择器
                System.out.println("连接服务器成功");
                doWrite(sc);//如果连接成功则就写数据
            }
            else
                {
                sc.register(selector,SelectionKey.OP_CONNECT);

            }

        }catch(Exception e)
        {e.printStackTrace();
        System.exit(1);
        }

        while(true)//只要是true，就进入死循环
        {
            try{
                /**客户端守候通道，把服务端传过来的东西交给函数处理*/
                selector.select(1000);
                Set<SelectionKey> selectionkey=selector.selectedKeys();
                /*SelectionKey为在选择器选择通道的一个注册器*/
                Iterator<SelectionKey> it=selectionkey.iterator();
                    SelectionKey key=null;
                    while(it.hasNext())
                    {
                        key=it.next();
                        it.remove();
                        try{
                            handleInput(selector,key);//交给函数来处理
                        }catch(Exception e){
                            if (key!=null)
                            {
                                key.channel();
                                if (key.channel()!=null)
                                    key.channel().close();
                            }
                        }
                    }
            }catch(Exception e){e.printStackTrace();}
        }
    }
    public static void doWrite(SocketChannel sc) throws IOException
    {
        byte[] str= UUID.randomUUID().toString().getBytes();//产生随机的字符串
        /**UUID.randomUUID()是产生一组唯一标识符的字符，不会重复*/
        ByteBuffer writerBuffer=ByteBuffer.allocate(str.length);//申请缓存区来分配字符长度
        writerBuffer.put(str);//把字符串放入缓存区里面
        writerBuffer.flip();
        sc.write(writerBuffer);//通过通道把缓存区内容输出出去
    }
    public static void handleInput(Selector selector,SelectionKey key)throws Exception
    {
        if(key.isValid())
        {
            //判断是否连接成功
            SocketChannel sc=(SocketChannel)key.channel();
            if(key.isConnectable())
            {
                if(sc.finishConnect())
                {
                    sc.register(selector,SelectionKey.OP_READ);
                }
            }
            if (key.isReadable())
            {
                ByteBuffer readBuffer=ByteBuffer.allocate(1024);
                int readBytes=sc.read(readBuffer);
                if(readBytes>0)
                {
                    readBuffer.flip();
                    byte[] bytes=new byte[readBuffer.remaining()];
                    readBuffer.get(bytes);
                    String body=new String(bytes,"UTF-8");//转码
                    System.out.println("客户端说："+body);
                }
                else if(readBytes<0)
                {
                    key.channel();//对端链路关闭
                    sc.close();
                }else
                {
                    System.out.println("服务器繁忙.....");
                }
            }
            Thread.sleep(3000);
            doWrite(sc);
        }
    }

}
